//------------------------------------------------------------------------------
//
// Copyright (c) 2002-2017 CodeSmith Tools, LLC.  All rights reserved.
//
// The terms of use for this software are contained in the file
// named sourcelicense.txt, which can be found in the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by the
// terms of this license.
//
// You must not remove this notice, or any other, from this software.
//
//------------------------------------------------------------------------------

using System;
using CodeSmith.Engine;
using System.Xml.XPath;
using System.Xml;
using CodeSmith.Engine.Schema;

namespace CodeSmith.Samples
{
    /// <summary>
    /// This class provides CodeSmith serialization support for DropDownEditorProperty.
    /// </summary>
    public class DropDownEditorPropertySerializer : IPropertySerializer
    {
        public DropDownEditorPropertySerializer()
        {
        }

        /// <summary>
        /// This method will be used to save the property value when a template is being compiled.
        /// </summary>
        /// <param name="context">Information about the target property.</param>
        /// <param name="propertyValue">The property to be saved.</param>
        /// <returns>An object that will be stored in a Hashtable during template compilation.</returns>
        public object SaveProperty(PropertySerializerContext context, object propertyValue)
        {
            // Nothing special needs to be done to save this property so we just return the unmodified property value.
            return propertyValue;
        }

        /// <summary>
        /// This method will be used to restore the property value after a template has been compiled.
        /// </summary>
        /// <param name="context">Information about the target property.</param>
        /// <param name="propertyValue">The property to be loaded.</param>
        /// <returns>The value to be assigned to the template property after it has been compiled.</returns>
        public object LoadProperty(PropertySerializerContext context, object propertyValue)
        {
            // Nothing special needs to be done to load this property so we just return the unmodified property value.
            return propertyValue;
        }

        /// <summary>
        /// This method will be used when serializing the property value to an XML property set.
        /// </summary>
        /// <param name="context">Information about the target property.</param>
        /// <param name="writer">The XML writer that the property value will be written to.</param>
        /// <param name="propertyValue">The property to be serialized.</param>
        public void WritePropertyXml(PropertySerializerContext context, System.Xml.XmlWriter writer, object propertyValue)
        {
            if (propertyValue == null) return;

            DropDownEditorProperty dropDownEditorPropertyValue = propertyValue as DropDownEditorProperty;
            if (dropDownEditorPropertyValue != null)
            {
                writer.WriteElementString("SampleBoolean", dropDownEditorPropertyValue.SampleBoolean.ToString());
                writer.WriteElementString("SampleString", dropDownEditorPropertyValue.SampleString);
            }
        }

        /// <summary>
        /// This method will be used when deserializing the property from an XML property set.
        /// </summary>
        /// <param name="context">Information about the target property.</param>
        /// <param name="propertyValue">The XML node to read the property value from.</param>
        /// <returns>The value to be assigned to the template property.</returns>
        public object ReadPropertyXml(PropertySerializerContext context, System.Xml.XmlNode propertyValue)
        {
            if (context.PropertyInfo.PropertyType != typeof(DropDownEditorProperty))
                return null;

            // use XPath to select out values
            XPathNavigator navigator = propertyValue.CreateNavigator();
            // we need to import the CodeSmith Namespace
            XmlNamespaceManager manager = new XmlNamespaceManager(navigator.NameTable);
            manager.AddNamespace("cs", CodeSmithProject.DefaultNamespace);

            // expression to select SampleBoolean value
            XPathExpression sampleBooleanExpression = XPathExpression.Compile("string(cs:SampleBoolean/text())", manager);
            string boolString = navigator.Evaluate(sampleBooleanExpression) as string;
            bool sampleBoolean;
            bool.TryParse(boolString, out sampleBoolean);

            // expression to select SampleString value
            XPathExpression sampleTextExpression = XPathExpression.Compile("string(cs:SampleString/text())", manager);
            string sampleString = navigator.Evaluate(sampleTextExpression) as string;

            // create and return
            DropDownEditorProperty dropDownEditorPropertyValue = new DropDownEditorProperty();
            dropDownEditorPropertyValue.SampleBoolean = sampleBoolean;
            dropDownEditorPropertyValue.SampleString = sampleString;
            return dropDownEditorPropertyValue;
        }

        /// <summary>
        /// This method will be used to parse a default value for a property when a template is being instantiated.
        /// </summary>
        /// <param name="context">Information about the target property.</param>
        /// <param name="defaultValue">The default value.</param>
        /// <returns>An object that will be assigned to the template property.</returns>
        public object ParseDefaultValue(PropertySerializerContext context, string defaultValue)
        {
            if (context.PropertyInfo.PropertyType == typeof(DropDownEditorProperty))
            {
                DropDownEditorProperty dropDownEditorPropertyValue = new DropDownEditorProperty();
                string[] values = defaultValue.Split(',');
                if (values.Length == 2)
                {
                    dropDownEditorPropertyValue.SampleString = values[0];
                    dropDownEditorPropertyValue.SampleBoolean = Boolean.Parse(values[1]);
                    return dropDownEditorPropertyValue;
                }
                return null;
            }

            return null;
        }
    }
}
